# coding:utf-8
# 用来管理自动化性能测试的接口

from flask import Flask, request
import json
from MBoomer import LocustResult, db, BoomerCase, LocustNode,BoomerRemark
import appconf
from functools import reduce
from sqlalchemy import not_, and_, or_
app = appconf.app



@app.route('/locust/node')
def srhSpaceNode():
    """查询所有可用的节点"""
    # master_ip = request.args.get("master_ip")
    # master_port = request.args.get("master_port")

    query = db.session().query(LocustNode)
    # if master_ip != '':
    #     query = query.filter(LocustNode.master_ip == master_ip)
    # if master_port != '':
    #     query = query.filter(LocustNode.master_port == master_port)
    query = query.filter(LocustNode.case_id == 0)
    data = query.all()
    list = []
    for d in data:
        # list.append({'id': d.id})
        master_host="http://%s:%s"%(d.master_ip,d.master_web_port)
        list.append(
            {'master_host': master_host, 'master_port': d.master_port, 'id': d.id})
    return json.dumps({'errorCode': '', 'data': list})


@app.route('/save/locust/node', methods=['POST'])
def saveSpaceNode():
    """保存可用节点"""
    content = request.json
    nodeId = content.get('nodeId')
    caseId = content.get('caseId')
    query = LocustNode.query.filter(and_(LocustNode.id == nodeId, LocustNode.case_id == 0)).first()
    if query:
        query.case_id = caseId
        db.session.commit()
        return json.dumps({'errorCode': ''})
    return json.dumps({'errorCode': '该节点已被占用，请重新抢占!'})


@app.route('/del/locust/node', methods=['POST'])
def delSpaceNode():
    """释放测试节点"""
    content = request.json
    nodeId = content.get('nodeId')

    query = LocustNode.query.filter(and_(LocustNode.id == nodeId)).first()
    if query:
        query.case_id = 0
        db.session.commit()
        return json.dumps({'errorCode': ''})
    return json.dumps({'errorCode': '','msg':'释放失败'})


def srhNodeCase(case_id):
    """当前case_id所占用的node"""
    query = db.session().query(LocustNode)
    query = query.filter(LocustNode.case_id == case_id)
    data = query.all()
    list = []
    for d in data:
        list.append({'master_ip': d.master_ip, 'master_port': d.master_port, 'master_web_port': d.master_web_port,'nodeId':d.id})
    return {'errorCode': '', 'data': list}


@app.route('/save/locust/case', methods=['POST'])
def saveCase():
    """保存提交的测试案例"""
    content = request.json
    BoomerCase(content['task_name'], json.dumps(content['case_json'])).add()
    return json.dumps({'errorCode': ''})

@app.route('/result/remark/save', methods=['POST'])
def saveRemark():
    content = request.json
    BoomerRemark(content['task_name'],content['note']).add()
    return json.dumps({'errorCode': ''})
@app.route('/result/remark/list')
def remarkList():
    task_name = request.args.get("task_name")
    query = db.session().query(BoomerRemark)
    if task_name != '':
        query = query.filter(BoomerRemark.task_name == task_name)
    query = query.order_by(BoomerRemark.id.desc())
    data = query.all()
    list = []
    for d in data:
        list.append({'last_time':d.last_time,'note':d.note})
    return json.dumps({'errorCode': '', 'data': list})


@app.route('/locust/case/list')
def locustList():
    """查询相关的case，还没有做分页的"""
    task_name = request.args.get("task_name")
    start_time = request.args.get("start_time")
    end_time = request.args.get("end_time")
    page = request.args.get("page")
    limit = request.args.get("limit")
    query = db.session().query(BoomerCase)
    if task_name != '':
        task_name = "%%%s%%" % task_name

        query = query.filter(BoomerCase.task_name.like(task_name))
    if start_time != '':
        query = query.filter(BoomerCase.last_time >= start_time)
    if end_time != '':
        query = query.filter(BoomerCase.last_time <= end_time)
    query = query.order_by(BoomerCase.id.desc())
    count = query.count()
    data = query.paginate(int(page), int(limit), False)
    #data = query.all()
    list = []
    for d in data.items:
        master_host_obj = srhNodeCase(d.id)
        if len(master_host_obj.get('data')):
            nodeData = master_host_obj.get('data')[0]
            master_host = "http://%s:%s" % (nodeData.get('master_ip'), nodeData.get('master_web_port'))
            master_node = nodeData.get('master_port')
            nodeId = nodeData.get('nodeId')
        else:
            master_host = ''
            master_node = ''
            nodeId = ''
        list.append({'task_name': d.task_name,
                     'case_json': json.loads(d.case_json),
                     'master_host': master_host,
                     'master_node': master_node,
                     'last_time': d.last_time,
                     'id': d.id,
                     'nodeId':nodeId
                     })
    return json.dumps({'errorCode': '', 'data': list,'count':count})


@app.route('/load/task')
def loadTask():
    """
    装载测试参数信息
    :return:
    """
    master_ip = request.args.get("master_ip")
    master_port = request.args.get("master_port")
    query = db.session().query(BoomerCase, LocustNode)
    query = query.join(LocustNode, LocustNode.case_id == BoomerCase.id)
    query = query.filter(and_(LocustNode.master_ip == master_ip, LocustNode.master_port == master_port))
    data = query.all()

    if data:
        for d in data:
            return json.dumps(
                {'task_name': d.BoomerCase.task_name, 'request_datas': json.loads(d.BoomerCase.case_json)})
    return json.dumps({'task_name': '', 'request_datas': []})


@app.route('/result/list/png')
def listPng():
    """生成的图表"""
    task_name = request.args.get("task_name")
    query = db.session().query(LocustResult)
    if task_name != '':
        query = query.filter(LocustResult.task_name == task_name)
    query = query.order_by(LocustResult.id.desc())
    data = query.all()
    list_avg_response_time = []
    list_current_rps = []
    list_user_count = []
    list_num_requests = []
    list_num_failures = []
    list_last_time = []
    for d in data:
        list_avg_response_time.append(d.avg_response_time)
        list_current_rps.append(d.current_rps)
        list_user_count.append(d.user_count)
        list_num_requests.append(d.num_requests)
        list_num_failures.append(d.num_failures)
        list_last_time.append(d.last_time)
    return json.dumps({'errorCode': '',
                       'list_avg_response_time': list_avg_response_time,
                       'list_user_count': list_user_count,
                       'list_num_requests': list_num_requests,
                       'list_num_failures': list_num_failures,
                       'list_last_time': list_last_time,
                       'list_current_rps': list_current_rps})


@app.route('/result/search')
def searchResult():
    """查询所有结果列表，还没有做分页的"""
    task_name = request.args.get("task_name")
    start_time = request.args.get("start_time")
    end_time = request.args.get("end_time")
    page = request.args.get("page")
    limit = request.args.get("limit")

    #   查询
    query = db.session().query(LocustResult)
    if start_time != '':
        query = query.filter(LocustResult.last_time >= start_time)
    if end_time != '':
        query = query.filter(LocustResult.last_time <= end_time)
    if task_name != '':
        task_name = "%%%s%%" % task_name
        query = query.filter(LocustResult.task_name.like(task_name))
    query = query.order_by(LocustResult.id.desc())
    count = query.count()
    #data = query.all()
    data = query.paginate(int(page), int(limit), False)
    list = []
    for d in data.items:
        list.append({'task_name': d.task_name,
                     'id':d.id,
                     'avg_response_time': d.avg_response_time,
                     'max_response_time': d.max_response_time,
                     'median_response_time': d.median_response_time,
                     'current_rps': d.current_rps,
                     'user_count': d.user_count,
                     'errors_count': d.errors_count,
                     'result_json': json.loads(d.result_json),
                     'last_time': d.last_time,
                     'num_failures': d.num_failures,
                     'num_requests': d.num_requests})
    #   list去重
    list_dict_duplicate_removal(list)
    return json.dumps({'errorCode': '', 'data': list,'count':count})


def list_dict_duplicate_removal(data_list):
    run_function = lambda x, y: x if y in x else x + [y]
    return reduce(run_function, [[], ] + data_list)


@app.route('/upload/stop/result', methods=['POST'])
def saveResult():
    """保存提交过来的测试数据"""
    content = request.json
    user_count = content.get('user_count')
    errors_count = len(content.get('errors'))
    for data in content.get('stats'):
        if data.get('safe_name') != 'Aggregated':
            task_name = data.get('method')
            avg_response_time = data.get('avg_response_time')
            max_response_time = data.get('max_response_time')
            median_response_time = data.get('median_response_time')
            ninetieth_response_time = data.get('ninetieth_response_time')
            current_rps = data.get('current_rps')
            num_failures = data.get('num_failures')
            num_requests = data.get('num_requests')

            LocustResult(task_name=task_name,
                         avg_response_time=avg_response_time,
                         max_response_time=max_response_time,
                         median_response_time=median_response_time,
                         ninetieth_response_time=ninetieth_response_time,
                         current_rps=current_rps,
                         user_count=user_count,
                         errors_count=errors_count,
                         result_json=json.dumps(content),
                         num_requests=num_requests,
                         num_failures=num_failures).add()
    return json.dumps({'errorCode': ''})


if __name__ == '__main__':
    # pass
    app.run(host='0.0.0.0', port=9012, debug=True)
